//package com.xiaoniu.timer;
//
//import io.vertx.core.Vertx;
//import io.vertx.core.VertxOptions;
//import io.vertx.core.json.JsonObject;
//import io.vertx.core.logging.Logger;
//import io.vertx.core.logging.LoggerFactory;
//import io.vertx.core.shareddata.LocalMap;
//import org.mapdb.DB;
//import org.mapdb.DBMaker;
//import org.mapdb.HTreeMap;
//import org.mapdb.Serializer;
//import org.springframework.context.ApplicationContext;
//
//import java.lang.reflect.Method;
//import java.text.ParseException;
//import java.util.Map;
//
//public class TimerUtils {
//
//  private static final Logger log = LoggerFactory.getLogger(TimerUtils.class);
//
//  private static final Vertx VERTX = Vertx.vertx(new VertxOptions().setBlockedThreadCheckInterval(50000));
//
//  // 周期性任务
//  private static final LocalMap<String, JsonObject> PeriodicJob = VERTX.sharedData().getLocalMap("PeriodicJob");
//  // 一次性任务
//  private static final LocalMap<String, JsonObject> TimeJob = VERTX.sharedData().getLocalMap("TimeJob");
//
//  // 存放 uuid - 任务Id
//  private static final LocalMap<String, Long> db = VERTX.sharedData().getLocalMap("uuid-jobId");
//
//  // Map DB start ============================
//  private static final DB mapDb = DBMaker.fileDB("vertx-timer-map.db").closeOnJvmShutdown().make();
//  private static final HTreeMap<String, String> mapDbPeriodicJob = mapDb.hashMap("PeriodicJob",
//          Serializer.STRING, Serializer.STRING).createOrOpen();
//  private static final HTreeMap<String, String> mapDbTimeJob = mapDb.hashMap("TimeJob",
//          Serializer.STRING, Serializer.STRING).createOrOpen();
//  private static final HTreeMap<String, Long> mapDbdb = mapDb.hashMap("db-uuid-jobId",
//          Serializer.STRING, Serializer.LONG).createOrOpen();
//  // Map DB end  ============================
//
//  private ApplicationContext context;
//
//  private TimerUtils() {
//  }
//
//  public static TimerUtils newInstance() {
//    mapDbPeriodicJob.forEach((k, v) -> PeriodicJob.put(k, new JsonObject(v)));
//    mapDbTimeJob.forEach((k, v) -> TimeJob.put(k, new JsonObject(v)));
//    mapDbdb.forEach((k, v) -> db.put(k, v));
//    mapDb.commit();
//    log.info("TimerUtils 初始化...");
//    return new TimerUtils();
//  }
//
//  public TimerUtils setSpringContext(ApplicationContext context) {
//    this.context = context;
//    this.recover();
//    log.info("TimerUtils 设置Spring 环境");
//    return this;
//  }
//
//  // 恢复 文件里的任务
//  private TimerUtils recover() {
//
//    PeriodicJob.forEach((uuid, jsonObject) -> {
//      String className = jsonObject.getString("className");
//      String methodName = jsonObject.getString("methodName");
//      String args = jsonObject.getString("args");
//      String time = jsonObject.getString("time");
//
//      Long aLong = executePeriodicJob(uuid, time, className, methodName, args);
//      db.put(uuid, aLong);
//      mapDbdb.put(uuid, aLong);
//      mapDb.commit();
//    });
//
//    TimeJob.forEach((uuid, jsonObject) -> {
//      String className = jsonObject.getString("className");
//      String methodName = jsonObject.getString("methodName");
//      String args = jsonObject.getString("args");
//      String time = jsonObject.getString("time");
//
//      long l = 0;
//      try {
//        l = TimerUtilsHelp.dateToMillisecond(time) - System.currentTimeMillis();
//      } catch (ParseException e) {
//        e.printStackTrace();
//      }
//
//      if (l > 0) {
//        log.debug("恢复 一次性任务 timer ==> " + l);
//        long l1 = execute(uuid, l, className, methodName, args);
//
//        db.put(uuid, l1);
//        mapDbdb.put(uuid, l1);
//
//        mapDb.commit();
//      }
//
//    });
//    return this;
//
//  }
//
//  public String addPeriodicJob(String time, String className, String methodName, String args) {
//    final String uuid = TimerUtilsHelp.uuid();
//    Long timerId = executePeriodicJob(uuid, time, className, methodName, args);
//    JsonObject jsonObject = new JsonObject().put("className", className)
//            .put("methodName", methodName).put("args", args).put("time", time).put("type", "periodic");
//    PeriodicJob.put(uuid, jsonObject);
//    db.put(uuid, timerId);
//
//    mapDbPeriodicJob.put(uuid, jsonObject.toString());
//    mapDbdb.put(uuid, timerId);
//
//    mapDb.commit();
//    log.debug("TimerUtils 添加周期性任务成功");
//    return uuid;
//  }
//
//  public String addTimerJob(String time, String className, String methodName, String args) throws ParseException {
//    String uuid = TimerUtilsHelp.uuid();
//    long l = TimerUtilsHelp.dateToMillisecond(time) - System.currentTimeMillis();
//    long execute = execute(uuid, l, className, methodName, args);
//    logTimerJob(System.currentTimeMillis() + l);
//    db.put(uuid, execute);
//    JsonObject jsonObject = new JsonObject().put("className", className)
//            .put("methodName", methodName).put("args", args).put("time", time).put("type", "time");
//    TimeJob.put(uuid, jsonObject);
//
//    mapDbdb.put(uuid, execute);
//    mapDbTimeJob.put(uuid, jsonObject.toString());
//    mapDb.commit();
//    log.debug("TimerUtils 添加一次性任务成功");
//    return uuid;
//  }
//
//  private Long executePeriodicJob(String uuid, String time, String className, String methodName, String args) {
//    try {
//      long l = 0;
//
////            if (time.length() == 1) {
////                String t = TimerUtilsHelp.year() + "-" + TimerUtilsHelp.month() + "-" + TimerUtilsHelp.day() + " "
////                        + LocalDateTime.now().getHour() +
////                        ":" + (LocalDateTime.now().getMinute() + Integer.parseInt(time));
////                l = TimerUtilsHelp.dateToMillisecond(t);
////                logPeriodicJob(l);
////            }
//
//      if (time.length() == 5) {
//        String t = TimerUtilsHelp.year() + "-" + TimerUtilsHelp.month() + "-" + TimerUtilsHelp.day() + " " + time;
//        l = TimerUtilsHelp.dateToMillisecond(t) > System.currentTimeMillis()
//                ? TimerUtilsHelp.dateToMillisecond(t)
//                : TimerUtilsHelp.dateToMillisecond(TimerUtilsHelp.year() + "-" + TimerUtilsHelp.month() + "-" +
//                (TimerUtilsHelp.day() + 1) + " " + time);
//        logPeriodicJob(l);
//      }
//
//      if (time.length() == 8) {
//        String t = TimerUtilsHelp.year() + "-" + TimerUtilsHelp.month() + "-" + time;
//        l = TimerUtilsHelp.dateToMillisecond(t) > System.currentTimeMillis()
//                ? TimerUtilsHelp.dateToMillisecond(t)
//                : TimerUtilsHelp.dateToMillisecond(TimerUtilsHelp.year() + "-" + (TimerUtilsHelp.month() + 1) + "-" + handlerMaxDay(time));
//        logPeriodicJob(l);
//      }
//
//      if (time.length() == 11) {
//        String t = TimerUtilsHelp.year() + "-" + time;
//        l = TimerUtilsHelp.dateToMillisecond(t) > System.currentTimeMillis()
//                ? TimerUtilsHelp.dateToMillisecond(t)
//                : TimerUtilsHelp.dateToMillisecond((TimerUtilsHelp.year() + 1) + "-" + time);
//        logPeriodicJob(l);
//      }
//
//      if (l == 0) {
//        throw new RuntimeException("参数不正确");
//      }
//
//      return VERTX.setTimer(l - System.currentTimeMillis(), r -> {
//        try {
//          Class c = Class.forName(className);
//          Method method = c.getMethod(methodName, String.class);
//          method.invoke(context.getBean(c), args);
//          Long id = executePeriodicJob(uuid, time, className, methodName, args);
//          db.put(uuid, id);
//          mapDbdb.put(uuid, id);
//          mapDb.commit();
//        } catch (ReflectiveOperationException e) {
//          e.printStackTrace();
//          log.error(e.getMessage());
//          throw new RuntimeException(e.getMessage());
//        }
//      });
//    } catch (Exception e) {
//      e.printStackTrace();
//      throw new RuntimeException(e.getMessage());
//    }
//  }
//
//  private Long execute(String uuid, long l, String className, String methodName, String args) {
//    return VERTX.setTimer(l, res -> {
//      try {
//        Class c = Class.forName(className);
//        Method method = c.getMethod(methodName, String.class);
//        method.invoke(context.getBean(c), args);
//        db.remove(uuid);
//        TimeJob.remove(uuid);
//
//        mapDbdb.remove(uuid);
//        mapDbTimeJob.remove(uuid);
//        mapDb.commit();
//      } catch (ReflectiveOperationException e) {
//        e.printStackTrace();
//        log.error(e.getMessage());
//        throw new RuntimeException(e.getMessage());
//      }
//    });
//  }
//
//  public boolean removeJob(String id) {
//    Long aLong = db.get(id);
//    if (aLong != null) {
//      db.remove(id);
//      if (PeriodicJob.containsKey(id)) {
//        PeriodicJob.remove(id);
//        mapDbPeriodicJob.remove(id);
//      }
//
//      mapDbdb.remove(id);
//      if (TimeJob.containsKey(id)) {
//        TimeJob.remove(id);
//        mapDbTimeJob.remove(id);
//      }
//
//      if (VERTX.cancelTimer(aLong)) {
//        log.debug("移除任务ID : " + id);
//        return true;
//      }
//      mapDb.commit();
//      return false;
//    }
//    return false;
//  }
//
//  public JsonObject findById(String uuid) {
//    return PeriodicJob.get(uuid) == null
//            ? (TimeJob.get(uuid) == null ? null : TimeJob.get(uuid))
//            : PeriodicJob.get(uuid);
//  }
//
//  public Map getPeriodicJob() {
//    return PeriodicJob;
//  }
//
//  public Map getTimeJob() {
//    return TimeJob;
//  }
//
//  public Map getDb() {
//    return db;
//  }
//
//  // map db =======================
//  public Map getDbPeriodicJob() {
//    return mapDbPeriodicJob;
//  }
//
//  public Map getDbTimeJob() {
//    return mapDbTimeJob;
//  }
//
//  public Map getDbMap() {
//    return mapDbdb;
//  }
//
//  // close map db
//  public void closeMapDb() {
//    if (!mapDbdb.isClosed())
//      mapDbdb.close();
//
//    if (!mapDbTimeJob.isClosed())
//      mapDbTimeJob.close();
//
//    if (!mapDbPeriodicJob.isClosed())
//      mapDbPeriodicJob.close();
//
//    mapDb.commit();
//    if (!mapDb.isClosed()) {
//      mapDb.close();
//    }
//  }
//
//
//  private void logPeriodicJob(long l) {
//    log.debug("周期性任务 :: 预执行时间：" + TimerUtilsHelp.formatDate(l));
//  }
//
//  private void logTimerJob(long l) {
//    log.debug("一次性任务 :: 预执行时间：" + TimerUtilsHelp.formatDate(l));
//  }
//
//  // 05 10:06
//  // 处理 特殊 月底日期
//  private String handlerMaxDay(String s) {
//    String[] arr = s.split(" ");
//    String day = arr[0];
//    Integer maxDay = TimerUtilsHelp.maxDay();
//    return Integer.parseInt(day) <= maxDay ? s : maxDay + " " + arr[1];
//  }
//}
//
